﻿using System;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Web.UI;
using System.Web.UI.WebControls;
using Medianamik.Core;
using Medianamik.Core.Interfaces;
using Medianamik.Core.Sugar;
using Medianamik.UI.Services;
using Telerik.Web.UI;

namespace Medianamik.UI.Web.UserControls
{
    public partial class MedianamikLinkPicker : UserControl
    {
        protected Guid? SelectedNodeId;

        private UrlsService _service;

        protected UrlsService UrlService
        {
            get
            {
                if (_service == null)
                    _service = new UrlsService();
                return _service;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            var page = Page as BasePage;

            if (page == null)
                Thread.CurrentThread.CurrentUICulture = new
                    CultureInfo(MedianamikContext.Current.Profile.UICultureName);

            if (!IsPostBack)
            {
                LoadCultureOptions();
                SetValues();
                LoadRootNodes();

                ProtocolPlaceHolder.Visible = MedianamikContext.Current.Profile.MaySpecifyMedianamikLinkProtocol;
            }
        }

        protected bool NodeHasUrl(Guid pageId, string cultureName)
        {
            return UrlService.GetUrls(pageId, cultureName).Count() > 0;
        }

        protected void ValidatePageChoice(object source, ServerValidateEventArgs args)
        {
            args.IsValid = !String.IsNullOrEmpty(PageChoice.SelectedValue) &&
                           NodeHasUrl(new Guid(PageChoice.SelectedValue), CultureChoice.SelectedValue);
        }

        protected void Select(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                const string script =
                    "getRadWindow().close({{href : '.@{0}|culture={1}|anchor={2}|protocol={3}.@', nodeid : '{0}', culture : '{1}', anchor : '{2}', protocol : '{3}'}});";

                ScriptManager.RegisterStartupScript(this, typeof(MedianamikLinkPicker), "CloseWindow",
                                                    String.Format(script, PageChoice.SelectedValue,
                                                                  CultureChoice.SelectedValue, Anchor.Text,
                                                                  ProtocolChoice.SelectedValue), true);
            }
        }

        protected void NodeExpand(object sender, RadTreeNodeEventArgs e)
        {
            ExpandNode(e.Node, false);
        }

        protected void CultureChoiceChanged(object sender, EventArgs e)
        {
            LoadRootNodes();
        }

        private Node _selectedNode;

        public Node SelectedNode
        {
            get
            {
                if (_selectedNode == null && SelectedNodeId.HasValue)
                {
                    _selectedNode = NodeManager.GetNode(SelectedNodeId.Value);

                    if (_selectedNode != null)
                        _selectedNode.DefaultCulture = new CultureInfo(CultureChoice.SelectedValue);
                }

                return _selectedNode;
            }
        }

        public string Resources(string classKey, string resourceKey)
        {
            return (String)GetGlobalResourceObject(classKey, resourceKey);
        }

        private void SetValues()
        {
            var href = Request.QueryString["href"];

            if (!String.IsNullOrEmpty(href))
            {
                var match = RegularExpressions.MedianamikLink.Match("href=\"" + href + "\"");
                if (match.Success)
                {
                    var idGroup = match.Groups["id"];
                    var cultureGroup = match.Groups["culture"];
                    var anchorGroup = match.Groups["anchor"];
                    var protocolGroup = match.Groups["protocol"];

                    if (idGroup != null && !String.IsNullOrEmpty(idGroup.Value))
                        StringHelper.IsGuid(idGroup.Value, ref SelectedNodeId);

                    if (cultureGroup != null && cultureGroup.Value != null &&
                        cultureGroup.Value.Length > 9)
                    {
                        //Remove |culture=
                        var cultureName = cultureGroup.Value.Substring(9, cultureGroup.Value.Length - 9);
                        CultureInfo culture = null;

                        if (StringHelper.IsCulture(cultureName, ref culture))
                            CultureChoice.SelectedValue = culture.Name;
                    }

                    if (anchorGroup != null && anchorGroup.Value != null &&
                        anchorGroup.Value.Length > 8)
                    {
                        Anchor.Text = anchorGroup.Value.Substring(8, anchorGroup.Value.Length - 8);
                    }

                    if (protocolGroup != null && protocolGroup.Value != null &&
                        protocolGroup.Value.Length > 10)
                    {
                        ProtocolChoice.SelectedValue = protocolGroup.Value.Substring(10,
                                                                                     protocolGroup.Value.Length - 10);
                    }
                }
            }
        }

        private void LoadCultureOptions()
        {
            CultureChoice.DataSource = ConfigManager.GetEditionCultures().Select(c => new CultureInfo(c.CultureName));
            CultureChoice.DataBind();
            CultureChoice.SelectedValue = MedianamikContext.Current.EditionCulture.Name;
        }

        private void LoadRootNodes()
        {
            PageChoice.Nodes.Clear();
            var modules = ConfigManager.GetAll<MedianamikModule>(CultureInfo.GetCultureInfo(CultureChoice.SelectedValue));

            foreach (var module in modules.Where(m => m.ChildNodeCount > 0
                && NodeManager.CountChildNodesByType(m, MedianamikTypes.BaseWebType, true) > 0))
            {
                var rootTreeNode = CreateTreeNode(module);
                rootTreeNode.ExpandMode = TreeNodeExpandMode.ServerSide;
                PageChoice.Nodes.Add(rootTreeNode);
            }

            GoToSelectedNodeId();
        }

        private void GoToSelectedNodeId()
        {
            if (PageChoice.Nodes.Count < 1)
                LoadRootNodes();

            if (SelectedNodeId.HasValue)
            {
                if (PageChoice.Nodes.Count > 0)
                {
                    var selectedTreeNode =
                        PageChoice.FindNodeByValue(SelectedNodeId.Value.ToString());

                    //Si le noeud n'est pas dans l'arbre
                    if (selectedTreeNode == null)
                    {
                        //Trouver le parent déjà dans l'arbre
                        var parentIDs = SelectedNode.GetParentIDs(true);
                        var i = 0;

                        while (selectedTreeNode == null && i < parentIDs.Count())
                        {
                            selectedTreeNode = PageChoice.FindNodeByValue(parentIDs.ElementAt(i).ToString());
                            i++;
                        }

                        if (selectedTreeNode != null)
                        {
                            //Expand parent node until SelectedNodeId reached
                            for (var j = i - 1; j >= 0; j--)
                            {
                                ExpandNode(selectedTreeNode, false);

                                if (j - 1 > 0)
                                {
                                    selectedTreeNode = selectedTreeNode.Nodes
                                        .FindNodeByValue(parentIDs.ElementAt(j - 1).ToString());
                                }
                            }

                            selectedTreeNode = selectedTreeNode.Nodes.FindNodeByValue(SelectedNodeId.Value.ToString());
                        }
                    }

                    ExpandNode(selectedTreeNode, true, SelectedNode);
                }
            }
        }

        private void ExpandNode(RadTreeNode node, bool selected)
        {
            ExpandNode(node, selected, null);
        }

        private void ExpandNode(RadTreeNode node, bool selected, INode rootNode)
        {
            if (selected)
            {
                PageChoice.ClearSelectedNodes();
            }

            if (node == null)
                throw new ApplicationException("The parent node is not part of the hierarchy.");

            if (node.ExpandMode == TreeNodeExpandMode.ServerSide)
            {
                var parentNode = rootNode ?? NodeManager.GetNode(new Guid(node.Value));

                foreach (var item in parentNode.GetChildContentNodes(new CultureInfo(CultureChoice.SelectedValue))
                    .Where(n => !n.NodeType.IsSystem && (n.NodeType.IsChildOf(MedianamikTypes.BaseWebType) ||
                                                         NodeManager.CountChildNodesByType(n,
                                                                                           MedianamikTypes.BaseWebType,
                                                                                           false) > 0)))
                {
                    var newNode = CreateTreeNode(item);

                    if (item.HasChildren)
                    {
                        newNode.ExpandMode = TreeNodeExpandMode.ServerSide;
                    }

                    node.Nodes.Add(newNode);
                }

                node.ExpandMode = TreeNodeExpandMode.ClientSide;
            }

            node.Expanded = true;
            node.ExpandParentNodes();
            node.Selected = selected;
        }

        protected override void Render(HtmlTextWriter writer)
        {
            const string script =
                @"
                <script type=""text/javascript"">
                    function getRadWindow(){{
                        if (window.radWindow){{return window.radWindow;}}
                        if (window.frameElement && window.frameElement.radWindow){{return window.frameElement.radWindow;}}
                                return null;
                    }}
                    
                    function initDialog(){{
                        var clientParameters = getRadWindow().ClientParameters;
                    }}

                    if (window.attachEvent){{window.attachEvent(""onload"", initDialog);}}
                    else if (window.addEventListener){{window.addEventListener(""load"", initDialog, false);}}
                    
                    function insertLink(sender, eventArgs){{
                        var treeview = $find('{0}');
                        var nodes = treeview.get_selectedNodes();
                        if(nodes.length > 0) {{
                            var node = nodes[0];
                            if (node.get_category() == ""Disabled"") {{
                                alert('todo');
                            }}
                            else {{
                                var closeArgument = {{}}; 
                                closeArgument.href = "".@"" + node.get_value() + "".@"";
                                closeArgument.text = node.get_text();
                                closeArgument.nodeid = node.get_value();
                                getRadWindow().close(closeArgument);
                            }}
                        }}
                        else
                            alert('todo');
                    }}
                </script>";

            writer.Write(String.Format(script, PageChoice.ClientID));
            base.Render(writer);
        }

        private RadTreeNode CreateTreeNode(INode node)
        {
            var result = new RadTreeNode
                             {
                                 Text = node.DisplayName,
                                 Value = node.ID.ToString(),
                                 ImageUrl = node.NodeType.IconPath ?? String.Empty,
                             };

            if (!node.NodeType.IsChildOf(MedianamikTypes.BaseWebType) ||
                !node.Instances.Exists(CultureChoice.SelectedValue))
            {
                result.Category = "Disabled";
                result.CssClass += " rtDisabled";
                result.HoveredCssClass = "rtDisabled";
                result.SelectedCssClass = "rtDisabled";
            }

            return result;
        }
    }
}